package com.huaxin.hxgateway.config;


import com.huaxin.hxjwt.config.JwtUtils;
import com.huaxin.hxjwt.entity.JwtModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;

@Component
public class JwtAuthGlobalFilter implements GlobalFilter, Ordered {

    private static final Logger log = LoggerFactory.getLogger(JwtAuthGlobalFilter.class);
    private static final String AUTHORIZATION_HEADER = "Authorization";
    private static final String BEARER_PREFIX = "Bearer ";

    // ✅ 定义所有需要传递的自定义 Header 名称
    private static final String HEADER_OPEN_ID = "X-Authenticated-Open-Id";
    private static final String HEADER_USER_ID = "X-Authenticated-User-Id";
    private static final String HEADER_USER_TYPE = "X-Authenticated-User-Type";
    private static final String HEADER_ORG_ID = "X-Authenticated-Org-Id";
    private static final String HEADER_FAMILY_ID = "X-Authenticated-Family-Id";

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getURI().getPath();

        log.info("【Gateway JWT Filter】收到请求: {} {}", request.getMethod(), path);

        if (shouldSkipAuthentication(path)) {
            log.info("【Gateway JWT Filter】跳过认证: {}", path);
            return chain.filter(exchange);
        }

        String authHeader = request.getHeaders().getFirst(AUTHORIZATION_HEADER);
        if (authHeader == null || !authHeader.startsWith(BEARER_PREFIX)) {
            log.warn("缺少或格式错误的 Authorization Header: {}", authHeader);
            return handleUnauthorized(exchange.getResponse(), "未登录");
        }

        String token = authHeader.substring(BEARER_PREFIX.length()).trim();
        if (token.isEmpty()) {
            log.warn("Authorization Header 中的 Token 为空");
            return handleUnauthorized(exchange.getResponse(), "Token 无效");
        }

        try {
            JwtModel jwtModel = JwtUtils.getJwtModelFromToken(token);
            log.info("JWT 验证成功，用户信息: openId={}, userId={}, userType={}, orgId={}, familyId={}",
                    jwtModel.getOpenId(), jwtModel.getUserId(), jwtModel.getUserType(), jwtModel.getOrgId(), jwtModel.getFamilyId());

            // ✅ 4. 创建新的请求，添加所有必要的用户信息 Header
            ServerHttpRequest modifiedRequest = request.mutate()
                    .header(HEADER_OPEN_ID, jwtModel.getOpenId()) // ✅ 添加 openId
                    .header(HEADER_USER_ID, jwtModel.getUserId())
                    .header(HEADER_USER_TYPE, String.valueOf(jwtModel.getUserType()))
                    .header(HEADER_ORG_ID, jwtModel.getOrgId())
                    .header(HEADER_FAMILY_ID, jwtModel.getFamilyId()) // ✅ 添加 familyId
                    .build();

            return chain.filter(exchange.mutate().request(modifiedRequest).build());

        } catch (Exception e) {
            log.warn("JWT 验证失败 (路径: {}): {}", path, e.getMessage());
            return handleUnauthorized(exchange.getResponse(), "Token 无效或已过期");
        }
    }

    @Override
    public int getOrder() {
        return -1; // 优先级很高
    }

    private boolean shouldSkipAuthentication(String path) {
        // ✅ 放行 Knife4j 相关路径（这些是网关自己的静态资源或聚合接口）
        if (path.startsWith("/swagger-ui") ||
                path.startsWith("/v3/api-docs") ||
                path.startsWith("/webjars/") ||
                path.equals("/doc.html") ||
                path.equals("/swagger-resources") ||
                path.equals("/swagger-resources/configuration/ui") ||
                path.equals("/swagger-resources/configuration/security")) {
            return true;
        }

        // ✅ 放行公开接口：路径必须带 /api，因为这是客户端请求的原始路径
        return List.of(
                "/api/v1/sys/users/weChatLogin",
                "/api/v1/sys/users/registerUser",
                "/api/v1/sys/users/passWordLogin",
                "/api/v1/sys/sms/sendSmsVerificationCode",
                "/api/v1/sys/sms/verifySmsVerificationCode",
                "/api/v1/sys/sysUser/login",
                "/api/v1/files/uploadFile",
                "/api/v1/sys/verification/getCaptcha",
                "/api/v1/sys/electricianArchives/electricianLogin",
                "/api/v1/workorder/inspectionOrder/queryInspectionOrderByOrgId",//根据企业id查询巡检工单
                "/api/v1/sys/organization/getOrganizationById",//根据id查询组织
                "/api/v1/device/electricalRoom/page",//查询电房
                "/api/v1/device/switchCabinet/page",//查询开关柜
                "/api/v1/workorder/inspectionOrderItem/list"//查询巡检工单项
        ).contains(path);
    }

    private Mono<Void> handleUnauthorized(ServerHttpResponse response, String message) {
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        response.getHeaders().set(HttpHeaders.CONTENT_TYPE, "application/json;charset=UTF-8");
        String body = String.format("{\"code\":401,\"msg\":\"%s\",\"success\":false}", message);
        return response.writeWith(Mono.just(response.bufferFactory().wrap(body.getBytes())));
    }
}